package com.yexx.starter.security.basic;

import com.yexx.starter.security.basic.constant.SecurityConstants;
import com.yexx.starter.security.basic.util.AuthUtils;
import com.yexx.starter.security.basic.util.JwtUtils;
import com.yexx.utils.CacheUtil;
import io.jsonwebtoken.Claims;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;

/**
 * Description: 自定义 登出handler
 *
 * @author: zuomin (myleszelic@outlook.com)
 * @date: 2020/10/30-11:37
 */
public class BasicLogoutHandler implements LogoutHandler {

    private CacheUtil cacheUtil;

    public BasicLogoutHandler(CacheUtil cacheUtil) {
        this.cacheUtil = cacheUtil;
    }

    @Override
    public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {

        String token = httpServletRequest.getHeader(SecurityConstants.TOKEN_HEADER);

        if (StringUtils.isEmpty(token)) {
            flush(httpServletResponse, SecurityConstants.RETURN_CODE.MISS_TOKEN, "miss token");
            return;
        }
        token = URLDecoder.decode(token, StandardCharsets.UTF_8);
        if (!token.startsWith(SecurityConstants.HEAD)) {
            flush(httpServletResponse, SecurityConstants.RETURN_CODE.MISS_BEARER, "miss Bearer");
            return;
        }
        token = token.substring(SecurityConstants.HEAD.length());
        Claims claims = JwtUtils.getClaim(token);
        if (claims == null) {
            flush(httpServletResponse, SecurityConstants.RETURN_CODE.INVALID_TOKEN, "invalid token");
            return;
        }
        String userIdStr = claims.getSubject();
        if (userIdStr == null) {
            flush(httpServletResponse, SecurityConstants.RETURN_CODE.EMPTY_SUBJECT, "miss userId");
            return;
        }

        Date expiredTime = claims.getExpiration();
        if ((System.currentTimeMillis() > expiredTime.getTime())) {
            flush(httpServletResponse, SecurityConstants.RETURN_CODE.TOKEN_EXPIRE, "token expire");
            return;
        }

        String tokenKey = AuthUtils.getTokenKey(userIdStr, token);
        cacheUtil.expire(tokenKey, 0);

    }

    private void flush(HttpServletResponse httpServletResponse, Integer code, String message) {
        try {
            httpServletResponse.setContentType("application/json;charset=utf-8");
            httpServletResponse.setCharacterEncoding("utf-8");
            try (PrintWriter out = httpServletResponse.getWriter()) {
                out.write(String.format(SecurityConstants.RETURN_JSON.DYNAMIC_CODE, code, message));
                out.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
